/* Sentinel - IRC Statistical and Operator Services
** s_string.c - String manipulation functions
**
** Copyright W. Campbell and others.  See README for more details
** Some code Copyright: Jonathan George, Kai Seidler, ircd-hybrid Team,
**                      IRCnet IRCD developers.
**
** $Id: s_string.c 7 2010-02-01 19:17:42Z dubkat $
*/

#include <string.h>
#include <ctype.h>
#include "s_string.h"
#include "slog.h"
#include "support.h"

/* Our own ctime function */
/* Modified for l10n - 12 f\xe9v 2002 -Hwy */
char *sctime(time_t stuff)
{
  static char buf[32];
  struct tm *ltm = localtime(&stuff);
  static char *gcc_sucks = "%c";

  /* %c is the POSIX localized replacement for ctime() */

  /* gcc complains about some non-BSD implementations not using
  ** a 4 digit year in some locales.  The warning can be ignored.
  **
  ** The lameness in this function is the only way I know of that
  ** the warning can be ignored.
  **
  ** Some versions of gcc support -Wno-y2k, but apparently it's
  ** only gcc3 and higher.  Using a custom -W parameter will cause
  ** issues when run with another compiler, so for now, this lameness
  ** stays.
  */
  strftime(buf, 32, gcc_sucks, ltm);
  return buf;
}

/* tokenize splits apart a message (in our case with the origin and command
** picked off already...
*/
int tokenize(char *message, char **parv)
{
  char *pos = NULL;
  char *next;
  int count = 0;

  if (!message)
  {
    /* Something is seriously wrong...bail */
    return -1;
  }

  /* First we find out if there's a : in the message, save that string
  ** somewhere so we can set it to the last param in parv
  ** Also make sure there's a space before it...if not, then we're
  ** screwed
  */
  pos = message;
  while (TRUE)
  {
    if ((pos = strchr(pos, ':')))
    {
      pos--;
      if (*pos != ' ')
      {
        /* There SHOULDN'T be a problem with this... */
        pos += 2;
        continue;
      }
      *pos = '\0';
      /* This is BAD - get rid of the space before the : */
      pos++;
      *pos = '\0';
      /* VERY BAD...over now though */
      pos++;
      break;
    }
    else
    {
      break;
    }
  }

  /* Now we take the beginning of message and find all the spaces...
  ** set them to \0 and use 'next' to go through the string
  */

  next = message;
  parv[0] = message;
  count = 1;

  while (*next)
  {
    if (count == MAXPARA - 1)
    {
      /* We've reached one less than our max limit
      ** to handle the parameter we already ripped off
      */
      slog(DEFAULT_LOG, L_DEBUG, "DEBUG: Reached the MAXPARA limit!");
      return count;
    }
    if (*next == ' ')
    {
      *next = '\0';
      next++;
      /* Eat any additional spaces */
      while (*next == ' ')
        next++;
      /* If it's the end of the string, it's simply
      ** an extra space before the :parameter.  Here we
      ** break.
      */
      if (*next == '\0')
        break;
      parv[count] = next;
      count++;
    }
    else
    {
      next++;
    }
  }

  if (pos)
  {
    parv[count] = pos;
    count++;
  }

  return count;
}

/* A generic tokenizer, tokenizes based on a specified character */
int generictoken(char delim, int size, char *message, char **parv)
{
  char *next;
  int count;

  if (!message)
  {
    /* Something is seriously wrong...bail */
    parv[0] = NULL;
    return 0;
  }

  /* Now we take the beginning of message and find all the spaces...
  ** set them to \0 and use 'next' to go through the string
  */
  next = message;
  parv[0] = next;
  count = 1;

  while (*next)
  {
    /* This is fine here, since we don't have a :delimited
    ** parameter like tokenize
    */
    if (count == size)
    {
      /* We've reached our limit */
      slog(DEFAULT_LOG, L_DEBUG, "Reached the size limit!");
      return count;
    }
    if (*next == delim)
    {
      *next = '\0';
      next++;
      /* Eat any additional delimiters */
      while (*next == delim)
        next++;
      /* If it's the end of the string, it's simply
      ** an extra space at the end.  Here we break.
      */
      if (*next == '\0')
        break;
      parv[count] = next;
      count++;
    }
    else
    {
      next++;
    }
  }

  return count;
}

void ExpandParv(char *dest, int max, int initial, int parc, char *parv[])
{
  int i;

  if (parv[initial])
    strlcpy(dest, parv[initial], max);
  for (i = initial + 1; i < parc; i++)
  {
    strlcat(dest, " ", max);
    strlcat(dest, parv[i], max);
  }
}

/* Return 1 if the string s is all lower case, return 0 if not */
int strislower(char *s)
{
  char *t;

  if (s == NULL)
    return 1;
  for (t = s; *t != '\0'; t++)
  {
    if (islower((int) *t) == 0)
    {
      return 0;
    }
  }
  return 1;
}

/* Remove CR and LF from the line input.  ASSUME that the line
** does NOT contain CR or LF in the middle
*/
void strip(char *line)
{
  char *c;

  if ((c = strchr(line, '\r')))
  {
    /* If we receive a CR, then we can just terminate the
    ** call here
    */
    *c = '\0';
    return ;
  }

  if ((c = strchr(line, '\n')))
  {
    *c = '\0';
    return ;
  }
}
